package com.csw.shuanfa.CodeImprove.exercise.future;

import com.csw.shuanfa.utils.ThreadPoolUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

@Slf4j
public class CompletableFuture_ThenCombine_ThenApply_ApplyToEither_Exceptionally {

    public static void main(String[] args) {

        ExecutorService threadPool = ThreadPoolUtil.getExecutorServiceCPU();

        try {
            log.error("monkey进入餐厅，点了份西红柿炒番茄");
            CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
                        log.error("厨师炒菜");
                        sleep(2, TimeUnit.SECONDS);
                        return "西红柿炒番茄好了";
                    }, threadPool)
                    //thenCombine
                    .thenCombine(CompletableFuture.supplyAsync(() -> {
                        log.error("服务员蒸饭");
                        sleep(3, TimeUnit.SECONDS);
                        return "米饭好了";
                    }, threadPool), (dish, rice) -> {
                        log.error("服务员打饭");
                        sleep(1, TimeUnit.SECONDS);
                        return dish + "," + rice;
                    });

            log.error("monkey在刷抖音");
            log.error("{},monkey开吃", cf.join());


            log.error("monkey吃完饭去结账，要求开发票");
            cf = CompletableFuture.supplyAsync(() -> {
                log.error("服务员收款");
                sleep(1, TimeUnit.SECONDS);
                return "20";
            }, threadPool).thenApply(money -> {
                log.error("服务员开发票，面额{}元", money);
                sleep(2, TimeUnit.SECONDS);
                return money + "元发票";
            });

            log.error("monkey接到朋友电话");
            log.error("monkey拿到{}，准备回家", cf.join());


            log.error("monkey走出餐厅，来到公交车站，等待301路或者918路公交到来");
            cf = CompletableFuture.supplyAsync(() -> {
                        log.error("301路公交正在赶来");
                        sleep(2, TimeUnit.SECONDS);
                        return "301路到了";
                    }, threadPool)
                    //applyToEither
                    .applyToEither(CompletableFuture.supplyAsync(() -> {
                        log.error("918路公交正在赶来");
                        sleep(1, TimeUnit.SECONDS);
                        return "918路到了";
                    }, threadPool), bus -> {
                        if (bus.startsWith("918")) {
                            throw new RuntimeException("918撞树了.......");
                        }
                        return bus;
                    })
                    //exceptionally
                    .exceptionally(e -> {
                        log.error("", e);
                        log.error("monkey叫出租车");
                        sleep(3, TimeUnit.SECONDS);
                        return "出租车到了";
                    });

            log.error("{},monkey坐车回家", cf.join());
        } catch (Exception e) {
            threadPool.shutdown();
            throw new RuntimeException(e);
        }


    }

    static void sleep(int t, TimeUnit u) {
        try {
            u.sleep(t);
        } catch (InterruptedException e) {
        }
    }
}